package com.wgh.pay.service.impl;

import com.wgh.pay.entity.PayLog;
import com.wgh.pay.mapper.PayLogMapper;
import com.wgh.pay.service.PayService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import io.seata.spring.annotation.GlobalTransactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 支付服务实现类
 */
@Service
public class PayServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayService {
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createPayOrder(Long orderId, BigDecimal amount, Integer payType, 
                                            String clientIp, String notifyUrl) {
        // 1. 检查订单是否已存在支付记录
        PayLog existingPayLog = baseMapper.selectByOrderId(orderId);
        if (existingPayLog != null && existingPayLog.getPayStatus() == 1) {
            // 订单已支付，返回支付成功信息
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "订单已支付");
            result.put("orderId", orderId);
            return result;
        }
        
        // 2. 生成支付流水号
        String transactionId = generateTransactionId();
        
        // 3. 创建支付日志
        PayLog payLog = new PayLog();
        payLog.setOrderId(orderId);
        payLog.setTransactionId(transactionId);
        payLog.setTotalAmount(amount);
        payLog.setPayType(payType);
        payLog.setPayStatus(0); // 未支付
        payLog.setClientIp(clientIp);
        payLog.setNotifyUrl(notifyUrl);
        payLog.setNotifyStatus(0); // 未回调
        payLog.setCreateTime(LocalDateTime.now());
        payLog.setUpdateTime(LocalDateTime.now());
        
        // 4. 保存支付日志
        save(payLog);
        
        // 5. 调用具体支付渠道创建支付订单
        Map<String, Object> payParams = buildPayParams(payLog);
        Map<String, Object> channelResult = callPayChannel(payParams);
        
        // 6. 返回支付参数
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("orderId", orderId);
        result.put("transactionId", transactionId);
        result.put("payType", payType);
        result.put("channelData", channelResult);
        
        return result;
    }
    
    @Override
    public PayLog queryPayOrderStatus(Long orderId) {
        return baseMapper.selectByOrderId(orderId);
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public boolean handlePayNotify(Map<String, String> notifyData, Integer payType) {
        // 1. 验证通知数据签名
        boolean verifyResult = verifyNotifyData(notifyData, payType);
        if (!verifyResult) {
            return false;
        }
        
        // 2. 解析通知数据
        String orderIdStr = notifyData.get("orderId");
        if (orderIdStr == null) {
            return false;
        }
        Long orderId = Long.parseLong(orderIdStr);
        String channelTradeNo = notifyData.get("channelTradeNo");
        
        // 3. 查询支付日志
        PayLog payLog = baseMapper.selectByOrderId(orderId);
        if (payLog == null || payLog.getPayStatus() == 1) {
            // 订单不存在或已支付
            return true; // 返回成功以避免重复通知
        }
        
        // 4. 更新支付状态
        payLog.setPayStatus(1); // 支付成功
        payLog.setPayTime(new Date());
        payLog.setChannelTradeNo(channelTradeNo);
        payLog.setUpdateTime(LocalDateTime.now());
        updateById(payLog);
        
        // 5. 异步通知业务系统（如订单服务）
        notifyBusinessSystem(payLog);
        
        return true;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean closePayOrder(Long orderId) {
        // 1. 查询支付日志
        PayLog payLog = baseMapper.selectByOrderId(orderId);
        if (payLog == null || payLog.getPayStatus() != 0) {
            // 订单不存在或已支付/已关闭
            return false;
        }
        
        // 2. 调用支付渠道关闭订单
        boolean closeResult = callClosePayChannel(payLog);
        if (!closeResult) {
            return false;
        }
        
        // 3. 更新支付日志状态
        payLog.setPayStatus(2); // 支付失败（关闭）
        payLog.setUpdateTime(LocalDateTime.now());
        updateById(payLog);
        
        return true;
    }
    
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> refund(Long orderId, BigDecimal refundAmount, String refundReason) {
        // 1. 查询支付日志
        PayLog payLog = baseMapper.selectByOrderId(orderId);
        if (payLog == null || payLog.getPayStatus() != 1) {
            // 订单不存在或未支付
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "订单不存在或未支付");
            return result;
        }
        
        // 2. 校验退款金额
        if (refundAmount.compareTo(payLog.getTotalAmount()) > 0) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "退款金额不能大于支付金额");
            return result;
        }
        
        // 3. 调用支付渠道发起退款
        Map<String, Object> refundParams = buildRefundParams(payLog, refundAmount, refundReason);
        Map<String, Object> channelResult = callRefundChannel(refundParams);
        
        // 4. 处理退款结果
        boolean refundSuccess = channelResult.containsKey("success") && (Boolean) channelResult.get("success");
        
        Map<String, Object> result = new HashMap<>();
        result.put("success", refundSuccess);
        result.put("orderId", orderId);
        result.put("refundAmount", refundAmount);
        result.put("channelData", channelResult);
        
        return result;
    }
    
    @Override
    public Map<String, Object> queryRefundStatus(Long orderId) {
        // 实现查询退款状态的逻辑
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("orderId", orderId);
        result.put("refundStatus", "PROCESSING"); // 模拟退款处理中状态
        return result;
    }
    
    @Override
    public Map<String, Object> getPayChannelConfig(Integer payType) {
        // 实现获取支付渠道配置的逻辑
        Map<String, Object> config = new HashMap<>();
        // 根据支付类型返回不同的配置
        switch (payType) {
            case 1: // 微信支付
                config.put("appId", "wx_app_id");
                config.put("mchId", "wx_mch_id");
                break;
            case 2: // 支付宝
                config.put("appId", "ali_app_id");
                config.put("sellerId", "ali_seller_id");
                break;
            case 3: // 银联支付
                config.put("merId", "unionpay_mer_id");
                break;
        }
        return config;
    }
    
    @Override
    public Map<String, Object> unifiedPay(Map<String, Object> payParams) {
        // 实现统一支付接口的逻辑
        // 根据支付类型选择不同的支付处理逻辑
        Integer payType = (Integer) payParams.get("payType");
        Map<String, Object> result = new HashMap<>();
        
        switch (payType) {
            case 1: // 微信支付
                // 调用微信支付处理逻辑
                result.put("success", true);
                result.put("payType", payType);
                result.put("message", "微信支付处理成功");
                break;
            case 2: // 支付宝
                // 调用支付宝处理逻辑
                result.put("success", true);
                result.put("payType", payType);
                result.put("message", "支付宝处理成功");
                break;
            case 3: // 银联支付
                // 调用银联支付处理逻辑
                result.put("success", true);
                result.put("payType", payType);
                result.put("message", "银联支付处理成功");
                break;
            default:
                result.put("success", false);
                result.put("message", "不支持的支付方式");
                break;
        }
        
        return result;
    }
    
    // 生成支付流水号
    private String generateTransactionId() {
        return "TX" + UUID.randomUUID().toString().replace("-", "").substring(0, 20);
    }
    
    // 构建支付参数
    private Map<String, Object> buildPayParams(PayLog payLog) {
        Map<String, Object> params = new HashMap<>();
        params.put("orderId", payLog.getOrderId());
        params.put("transactionId", payLog.getTransactionId());
        params.put("amount", payLog.getTotalAmount());
        params.put("payType", payLog.getPayType());
        params.put("clientIp", payLog.getClientIp());
        params.put("notifyUrl", payLog.getNotifyUrl());
        return params;
    }
    
    // 调用支付渠道
    private Map<String, Object> callPayChannel(Map<String, Object> payParams) {
        // 模拟调用支付渠道
        Map<String, Object> result = new HashMap<>();
        Integer payType = (Integer) payParams.get("payType");
        
        if (payType == 1) { // 微信支付
            result.put("codeUrl", "weixin://wxpay/bizpayurl?pr=abc123");
            result.put("tradeType", "NATIVE");
        } else if (payType == 2) { // 支付宝
            result.put("formData", "<form action='...'></form>");
        } else if (payType == 3) { // 银联支付
            result.put("tn", "202305201234567890");
        }
        
        return result;
    }
    
    // 验证通知数据
    private boolean verifyNotifyData(Map<String, String> notifyData, Integer payType) {
        // 模拟验证通知数据
        return notifyData.containsKey("sign") && notifyData.containsKey("orderId");
    }
    
    // 通知业务系统
    private void notifyBusinessSystem(PayLog payLog) {
        // 异步通知订单服务等业务系统
        // 可以使用消息队列或HTTP请求
        System.out.println("通知业务系统，订单" + payLog.getOrderId() + "支付成功");
    }
    
    // 调用支付渠道关闭订单
    private boolean callClosePayChannel(PayLog payLog) {
        // 模拟调用支付渠道关闭订单
        return true;
    }
    
    // 构建退款参数
    private Map<String, Object> buildRefundParams(PayLog payLog, BigDecimal refundAmount, String refundReason) {
        Map<String, Object> params = new HashMap<>();
        params.put("orderId", payLog.getOrderId());
        params.put("transactionId", payLog.getTransactionId());
        params.put("refundAmount", refundAmount);
        params.put("refundReason", refundReason);
        params.put("payType", payLog.getPayType());
        return params;
    }
    
    // 调用退款渠道
    private Map<String, Object> callRefundChannel(Map<String, Object> refundParams) {
        // 模拟调用退款渠道
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("refundId", "RF" + UUID.randomUUID().toString().substring(0, 10));
        return result;
    }
}